package com.waltercedric.tuxdroid.buildserver.teamcity5;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Set;

import jetbrains.buildServer.Build;
import jetbrains.buildServer.notification.Notificator;
import jetbrains.buildServer.notification.NotificatorRegistry;
import jetbrains.buildServer.responsibility.TestNameResponsibilityEntry;
import jetbrains.buildServer.serverSide.SBuildType;
import jetbrains.buildServer.serverSide.SProject;
import jetbrains.buildServer.serverSide.SRunningBuild;
import jetbrains.buildServer.serverSide.UserPropertyInfo;
import jetbrains.buildServer.users.NotificatorPropertyKey;
import jetbrains.buildServer.users.PropertyKey;
import jetbrains.buildServer.users.SUser;
import jetbrains.buildServer.vcs.VcsRoot;

import com.waltercedric.tuxdroid.buildserver.teamcity.TuxDroidNotificator;

public class TuxDroidNotificator5 extends TuxDroidNotificator implements
		Notificator {

	private static final PropertyKey ATTITUNE_BUILD_FAILED = new NotificatorPropertyKey(
			TYPE, "AttituneBuildFailed");
	private static final PropertyKey ATTITUNE_BUILD_FAILING = new NotificatorPropertyKey(
			TYPE, "AttituneBuildFailing");
	private static final PropertyKey ATTITUNE_BUILD_HANGING = new NotificatorPropertyKey(
			TYPE, "AttituneBuildHanging");
	private static final PropertyKey ATTITUNE_BUILD_LABELING_FAILED = new NotificatorPropertyKey(
			TYPE, "AttituneBuildLabelingFailed");
	private static final PropertyKey ATTITUNE_BUILD_RESPONSIBLE_CHANGED = new NotificatorPropertyKey(
			TYPE, "AttituneBuildResponsibleChanged");
	private static final PropertyKey ATTITUNE_BUILD_RESPONSIBLE_ASSIGNED = new NotificatorPropertyKey(
			TYPE, "AttituneBuildResponsibleAssigned");
	private static final PropertyKey ATTITUNE_BUILD_STARTED = new NotificatorPropertyKey(
			TYPE, "AttituneBuildStarted");
	private static final PropertyKey ATTITUNE_BUILD_SUCCESSFUL = new NotificatorPropertyKey(
			TYPE, "AttituneBuildSuccessful");

	private static final PropertyKey TUXDROID_IP = new NotificatorPropertyKey(
			TYPE, "TuxDroidIP");
	private static final PropertyKey TUXDROID_PORT = new NotificatorPropertyKey(
			TYPE, "TuxDroidPort");

	public TuxDroidNotificator5(NotificatorRegistry notificatorRegistry)
			throws IOException {
		ArrayList<UserPropertyInfo> userProps = new ArrayList<UserPropertyInfo>();
		userProps.add(new UserPropertyInfo("TuxDroidIP", "TuxDroid IP"));
		userProps.add(new UserPropertyInfo("TuxDroidPort", "TuxDroid Port"));

		userProps.add(new UserPropertyInfo("AttituneBuildFailed", "Failed"));
		userProps.add(new UserPropertyInfo("AttituneBuildFailing", "Failing"));
		userProps.add(new UserPropertyInfo("AttituneBuildHanging", "Hanging"));
		userProps.add(new UserPropertyInfo("AttituneBuildLabelingFailed",
				"Labelling Failed"));
		userProps.add(new UserPropertyInfo("AttituneBuildResponsibleChanged",
				"Responsible Changed"));
		userProps.add(new UserPropertyInfo("AttituneBuildResponsibleAssigned",
				"Responsible Assigned"));
		userProps.add(new UserPropertyInfo("AttituneBuildStarted", "Started"));
		userProps.add(new UserPropertyInfo("AttituneBuildSuccessful",
				"Successful"));

		notificatorRegistry.register(this, userProps);
	}

	protected void doNotifications(String freeUserChoice, String message,
			SUser user) {
		// can be user dependent, imagine a Tux Droid farm :-)
		Integer port = Integer.parseInt(user.getPropertyValue(TUXDROID_PORT));
		String ipAdress = user.getPropertyValue(TUXDROID_IP);
		doNotifications(freeUserChoice, message, ipAdress, port);
	}

	public void notifyBuildFailed(SRunningBuild sRunningBuild, Set<SUser> sUsers) {
		for (SUser user : sUsers) {
			String freeUserChoice = user
					.getPropertyValue(ATTITUNE_BUILD_FAILED);
			freeUserChoice = filterPlaceHolder(sRunningBuild, freeUserChoice,
					user);

			String defaultMessage = "Build " + sRunningBuild.getFullName()
					+ " failed.";

			doNotifications(freeUserChoice, defaultMessage, user);
		}
	}

	public void notifyBuildFailing(SRunningBuild sRunningBuild,
			Set<SUser> sUsers) {
		for (SUser user : sUsers) {
			String freeUserChoice = user
					.getPropertyValue(ATTITUNE_BUILD_FAILING);
			freeUserChoice = filterPlaceHolder(sRunningBuild, freeUserChoice,
					user);
			doNotifications(freeUserChoice, "Build "
					+ sRunningBuild.getFullName() + " failing.", user);
		}
	}

	public void notifyBuildProbablyHanging(SRunningBuild sRunningBuild,
			Set<SUser> sUsers) {
		for (SUser user : sUsers) {
			String freeUserChoice = user
					.getPropertyValue(ATTITUNE_BUILD_HANGING);
			freeUserChoice = filterPlaceHolder(sRunningBuild, freeUserChoice,
					user);
			doNotifications(freeUserChoice, "Build "
					+ sRunningBuild.getFullName() + " probably hanging.", user);
		}
	}

	public void notifyBuildStarted(SRunningBuild sRunningBuild,
			Set<SUser> sUsers) {
		for (SUser user : sUsers) {
			String freeUserChoice = user
					.getPropertyValue(ATTITUNE_BUILD_STARTED);
			freeUserChoice = filterPlaceHolder(sRunningBuild, freeUserChoice,
					user);
			doNotifications(freeUserChoice, "Build "
					+ sRunningBuild.getFullName() + " started.", user);
		}
	}

	public void notifyBuildSuccessful(SRunningBuild sRunningBuild,
			Set<SUser> sUsers) {
		for (SUser user : sUsers) {
			String freeUserChoice = user
					.getPropertyValue(ATTITUNE_BUILD_SUCCESSFUL);
			freeUserChoice = filterPlaceHolder(sRunningBuild, freeUserChoice,
					user);
			doNotifications(freeUserChoice, "Build "
					+ sRunningBuild.getFullName() + " successful.", user);
		}
	}

	public void notifyLabelingFailed(Build sRunningBuild, VcsRoot aVcsRoot,
			Throwable arg2, Set<SUser> sUsers) {
		for (SUser user : sUsers) {
			String freeUserChoice = user
					.getPropertyValue(ATTITUNE_BUILD_LABELING_FAILED);
			freeUserChoice = filterPlaceHolder(sRunningBuild, freeUserChoice,
					user);
			doNotifications(freeUserChoice, "Build "
					+ sRunningBuild.getFullName()
					+ " labeling failed in VCS Root " + aVcsRoot, user);
		}
	}

	public void notifyResponsibleChanged(SBuildType sRunningBuild,
			Set<SUser> sUsers) {
		for (SUser user : sUsers) {
			String freeUserChoice = user
					.getPropertyValue(ATTITUNE_BUILD_RESPONSIBLE_CHANGED);
			freeUserChoice = filterPlaceHolder(sRunningBuild, freeUserChoice,
					user);
			doNotifications(freeUserChoice,
					"Build " + sRunningBuild.getFullName()
							+ " responsible has changed.", user);
		}
	}

	public String filterPlaceHolder(Build runningBuild, String freeUserChoice,
			SUser user) {
		freeUserChoice = freeUserChoice.replaceAll("%b", runningBuild
				.getFullName());
		freeUserChoice = freeUserChoice.replaceAll("%u", user.getUsername());
		freeUserChoice = freeUserChoice.replaceAll("%n", user.getName());
		freeUserChoice = freeUserChoice.replaceAll("%a", runningBuild
				.getFullName());
		freeUserChoice = freeUserChoice.replaceAll("%#", runningBuild
				.getBuildNumber());
		return freeUserChoice;
	}

	public String filterPlaceHolder(SBuildType runningBuild,
			String freeUserChoice, SUser user) {
		freeUserChoice = freeUserChoice.replaceAll("%b", runningBuild
				.getFullName());
		freeUserChoice = freeUserChoice.replaceAll("%u", user.getUsername());
		freeUserChoice = freeUserChoice.replaceAll("%n", user.getName());
		freeUserChoice = freeUserChoice
				.replaceAll("%a", runningBuild.getName());
		return freeUserChoice;
	}

	public String filterPlaceHolder(SProject sProject, String freeUserChoice,
			SUser user) {
		freeUserChoice = freeUserChoice.replaceAll("%b", sProject.getName());
		freeUserChoice = freeUserChoice.replaceAll("%u", user.getUsername());
		freeUserChoice = freeUserChoice.replaceAll("%n", user.getName());
		return freeUserChoice;
	}

	public String filterPlaceHolder(SRunningBuild sRunningBuild,
			String freeUserChoice, SUser user) {
		freeUserChoice = freeUserChoice.replaceAll("%b", sRunningBuild
				.getFullName());
		freeUserChoice = freeUserChoice.replaceAll("%u", user.getUsername());
		freeUserChoice = freeUserChoice.replaceAll("%n", user.getName());
		freeUserChoice = freeUserChoice.replaceAll("%a", sRunningBuild
				.getAgent().getName());
		freeUserChoice = freeUserChoice.replaceAll("%#", sRunningBuild
				.getBuildNumber());
		return freeUserChoice;
	}

	@Override
	public void notifyResponsibleAssigned(SBuildType sRunningBuild,
			Set<SUser> sUsers) {
		for (SUser user : sUsers) {
			String freeUserChoice = user
					.getPropertyValue(ATTITUNE_BUILD_RESPONSIBLE_ASSIGNED);
			freeUserChoice = filterPlaceHolder(sRunningBuild, freeUserChoice,
					user);
			doNotifications(freeUserChoice,
					"Build " + sRunningBuild.getFullName()
							+ " responsible has changed.", user);
		}
	}

	@Override
	public void notifyResponsibleAssigned(TestNameResponsibilityEntry arg0,
			TestNameResponsibilityEntry arg1, SProject sProject,
			Set<SUser> sUsers) {
		for (SUser user : sUsers) {
			String freeUserChoice = user
					.getPropertyValue(ATTITUNE_BUILD_RESPONSIBLE_ASSIGNED);
			freeUserChoice = filterPlaceHolder(sProject, freeUserChoice, user);
			doNotifications(freeUserChoice, "Build " + sProject.getName()
					+ " responsible assigned.", user);
		}

	}

	@Override
	public void notifyResponsibleChanged(TestNameResponsibilityEntry arg0,
			TestNameResponsibilityEntry arg1, SProject sProject,
			Set<SUser> sUsers) {
		for (SUser user : sUsers) {
			String freeUserChoice = user
					.getPropertyValue(ATTITUNE_BUILD_RESPONSIBLE_CHANGED);
			freeUserChoice = filterPlaceHolder(sProject, freeUserChoice, user);
			doNotifications(freeUserChoice, "Build " + sProject.getName()
					+ " responsible has changed.", user);
		}

	}

}
